package org.example.alicloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.util.TimeUtil;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.example.alicloud.handler.CustomerBlockHandler;
import org.example.alicloud.model.CommonResult;
import org.example.alicloud.model.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author gaoqiang
 * @created 2021-05-08
 */
@RestController
@Slf4j
public class FlowLimitController {

    private static HashMap<Long, Payment> hashMap = new HashMap<Long, Payment>();
    static {
        hashMap.put(1L, new Payment(1L, "21281"));
        hashMap.put(2L, new Payment(2L, "21282"));
        hashMap.put(3L, new Payment(3L, "21283"));
    }

    @GetMapping("/testA")
    public String testA(){
        try {
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "-----testA";
    }

    @GetMapping("/testB")
    public String testB(){
        log.info("current thread name: {} method -- testB", Thread.currentThread().getName());
        return "-----testb";
    }

    @GetMapping("/testC")
    @SentinelResource(value = "testC",
            fallbackClass = CustomerBlockHandler.class,
            fallback = "handlerDegradeException2",
            blockHandler = "handlerException",
            blockHandlerClass = CustomerBlockHandler.class
    )
    public String testC(){
        log.info("current thread name: {} method -- testC", Thread.currentThread().getName());
        int age = 10/0;
        return "-----testC";
    }

    @GetMapping("/testDegrade")
    @SentinelResource(value = "testDegrade",
            fallbackClass = CustomerBlockHandler.class,
            fallback = "handlerDegradeException")
    public CommonResult testDegrade(){
        log.info("current thread name: {} method -- testDegrade", Thread.currentThread().getName());
        int age = 10/0;
        return new CommonResult(444, "return from test degrade", null);
    }

    @GetMapping("/testBlockAndDegrade/{id}")
    //@SentinelResource(value = "testDegrade2", fallbackClass = CustomerBlockHandler.class, fallback = "handleFallbackException")
    //@SentinelResource(value = "testDegrade2", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleBlockException")
    @SentinelResource(value = "testDegrade2", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerBlockException", fallbackClass = CustomerBlockHandler.class, fallback = "handleFallbackException")
    //@SentinelResource(value = "testDegrade2", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerFallbackException", fallbackClass = CustomerBlockHandler.class, fallback = "handleFallbackException", exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult testBlockAndDegrade(@PathVariable("id") Long id) {
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult<>(200, "nacos registry, from hash map \t id:"+id, payment);
        //restTemplate.getForObject(SERVICE_URL+"/payment/"+id, CommonResult.class, id);
        if (id == 4) {
            throw new IllegalArgumentException("IllegalArgumentException, 非法参数异常。。。");
        } else if (result.getData() == null) {
            throw new NullPointerException("该ID没有对应记录，空指针异常。。。");
        }
        return result;
    }

    @GetMapping("/testD")
    public String testD(){
        log.info("current thread name: {} method -- testD RT", Thread.currentThread().getName());
        try {
            TimeUnit.MILLISECONDS.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "-----testD RT";
    }

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_hotKey")
    //SentinelResource处理的是sentinel控制台配置的违规情况，由blockHandler指定的方法来处理，不负责处理程序运行产生的异常
    //blockHandler：需要指定一个服务降级后的处理方法，否则直接返回异常信息给前台
    public String testHotkey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2){
        return "------testHotkey";
    }

    public String deal_hotKey(String p1, String p2, BlockException exception){
        return "自定义降级处理";
    }
}
